package org.webmev.controllers;

import java.io.*;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.webmev.utils.CountInputStream;
import org.webmev.utils.WriteableInputStream;

public class FileUploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    private static final String TMP_DIR_PATH = "/tempfiles";
    private File tmpDir;
    private static final String DESTINATION_DIR_PATH = "/files";
    private File destinationDir;
    private HttpSession session;
    private long totalsize = 0;
    long count = 0;

    public FileUploadServlet() {
        super();
    }

    public void init(ServletConfig config) throws ServletException {

        super.init(config);
        String realPath = getServletContext().getRealPath(TMP_DIR_PATH);
        tmpDir = new File(realPath);
        if (!tmpDir.isDirectory()) {
            throw new ServletException(TMP_DIR_PATH + " is not a directory");
        }

        realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
        destinationDir = new File(realPath);
        if (!destinationDir.isDirectory()) {
            throw new ServletException(DESTINATION_DIR_PATH + " is not a directory");
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        session = request.getSession(true);
        //PrintWriter to send the JSON response back
        PrintWriter out = response.getWriter();
        //set content type
        response.setContentType("text/html");
        //Create a JSON object to send response
        JSONObject myObj = new JSONObject();

        myObj.put("count", session.getAttribute("uploadProgress"));
        //convert the JSON object to string and send the response back
        out.println(myObj.toString());
        out.close();
        //System.out.println(session.getAttribute("uploadProgress"));
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        session = request.getSession(true);

        session.setAttribute("uploadProgress", 0);

        //PrintWriter to send the JSON response back
        PrintWriter out = response.getWriter();
        //set content type
        response.setContentType("text/html");

        DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();

        //Set the size threshold, above which content will be stored on disk.
        fileItemFactory.setSizeThreshold(1 * 1024 * 1024); //1 MB

        //Set the temporary directory to store the uploaded files of size above threshold.
        fileItemFactory.setRepository(tmpDir);

        ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
        try {

            //Parse the request
            List items = uploadHandler.parseRequest(request);
            Iterator iterator = items.iterator();
            while (iterator.hasNext()) {
                FileItem item = (FileItem) iterator.next();

                //Handle Form Fields
                if (item.isFormField()) {
                    //System.out.println("Parameter = "+item.getFieldName()+", Value = "+item.getString());                  
                } //Handle Uploaded files.
                else {
                    System.out.println("Field Name = " + item.getFieldName()
                            + ", File Name = " + item.getName()
                            + ", Content type = " + item.getContentType()
                            + ", File Size = " + item.getSize());
                    //Write file to the ultimate location.
                    totalsize = item.getSize();
                    File file = new File(destinationDir, item.getName());
                    new WriteableInputStream(
                            new CountInputStream(
                            new BufferedInputStream(item.getInputStream(), 1024), new CountInputStream.Action() {

                        long count = 0;

                        public void apply(int c) {
                            count++;
                            session.setAttribute("uploadProgress", 100 * count / totalsize);
                        }
                    })).writeTo(new BufferedOutputStream(new FileOutputStream(file)));
                    item.write(file);
                }
                session.setAttribute("uploadProgress", 0);
                //Create a JSON object to send response
                JSONObject myObj = new JSONObject();
                //sets success to true
                myObj.put("success", true);
                myObj.put("file", item.getName());
                myObj.put("size", item.getSize());
                //convert the JSON object to string and send the response back
                out.println(myObj.toString());
                out.close();

            }
        } catch (FileUploadException ex) {
            log("Error encountered while parsing the request", ex);
        } catch (Exception ex) {
            log("Error encountered while uploading file", ex);
        }
    }
}
